package com.gking.centerSystem.service.UserRoles;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gking.centerSystem.common.ProgramException;
import com.gking.centerSystem.common.Result;
import com.gking.centerSystem.entity.*;
import com.gking.centerSystem.entity.dto.UserRoleListDto;
import com.gking.centerSystem.entity.enums.UserDataSetTypeEnum;
import com.gking.centerSystem.mapper.RolePermissionsMapper;
import com.gking.centerSystem.mapper.RolesMapper;
import com.gking.centerSystem.mapper.UserMapper;
import com.gking.centerSystem.mapper.UserRolesMapper;
import com.gking.centerSystem.service.Roles.RolesService;
import com.gking.centerSystem.utils.commonUtil.CustomEncryptorUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;


@Slf4j
@Service
public class UserRolesServiceImpl extends ServiceImpl<UserRolesMapper, UserRoles> implements UserRolesService {

    @Autowired
    private RolesService rolesService;

    @Resource
    private UserRolesMapper userRolesMapper;

    @Resource
    private RolePermissionsMapper rolePermissionsMapper;

    @Resource
    private UserMapper userMapper;

    @Resource
    private RolesMapper rolesMapper;

    /**
     * 获取用户角色详情(包含权限code详情)
     *
     * @param userId 用户id
     * @return s
     */
    @Override
    public Result<UserRoleListDto> getUserRolesDetail(String userId) {
        if (userId.isEmpty()) return Result.error("请将参数补充完整");

        try {
            List<Roles> roleList = userRolesMapper.findUsersByCriteria(userId);
            if (roleList.isEmpty()) return Result.success("获取用户角色列表成功！", new UserRoleListDto());

            List<String> ids = roleList.stream()
                    .map(Roles::getId)
                    .collect(Collectors.toList());

            List<String> rolesNameList = new ArrayList<>();
            List<String> rolesIdList = new ArrayList<>();
            List<Roles> rolesList = new ArrayList<>();

            Map<String, Roles> map = new HashMap<>();
            for (Roles r : roleList) map.put(r.getId(), r);

            for (String id : ids) {
                Roles roles = map.get(id);
                rolesNameList.add(roles.getName());
                rolesIdList.add(roles.getId());
                rolesList.add(roles);
            }

            UserRoleListDto userRoleListDto = new UserRoleListDto();
            userRoleListDto.setRoleNameList(rolesNameList);
            userRoleListDto.setRoleIdList(rolesIdList);
            userRoleListDto.setRolesList(rolesList);

            // 查询角色详情时，顺便查询权限code详情
            LambdaQueryWrapper<RolePermissions> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(RolePermissions::getRoleId, rolesIdList);
            List<RolePermissions> rolePermissions = rolePermissionsMapper.selectList(wrapper);
            List<String> permIds = rolePermissions.stream()
                    .map(RolePermissions::getPermissionId)
                    .collect(Collectors.toList());
            List<Permissions> permissionsByIds = rolePermissionsMapper.getPermissionsByIds(permIds);
            List<String> permissions = permissionsByIds.stream()
                    .map(Permissions::getCode)
                    .collect(Collectors.toList());

            userRoleListDto.setPermissionList(permissions);

            return Result.success("获取用户角色列表成功！", userRoleListDto);
        } catch (Exception e) {
            log.error("获取用户角色列表失败！ {}", e.getMessage());
            throw new ProgramException();
        }
    }

    /**
     * 为用户设置角色
     *
     * @param userId     用户id
     * @param type       类型（refresh, add, remove）
     * @param roleIdList 角色id 列表
     * @return s
     */
    @Transactional
    @Override
    public Result<String> setUserRoles(String userId, String type, List<String> roleIdList) {
        try {
            if (userId.isEmpty() || type.isEmpty()) return Result.error("请将参数补充完整");
            if (UserDataSetTypeEnum.getEnumByValue(type) == null) return Result.error("type参数错误");
            if (roleIdList == null || roleIdList.isEmpty()) return Result.error("角色列表不能为空");

            // 校验用户信息
            LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(User::getId, userId);
            queryWrapper.eq(User::getIsDelete, 0);

            User user = userMapper.selectOne(queryWrapper);
            if (user == null) return Result.error("用户不存在");

            // 校验角色信息
            LambdaQueryWrapper<Roles> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(Roles::getId, roleIdList);
            wrapper.eq(Roles::getIsDelete, 0);

            List<Roles> rolesList = rolesMapper.selectList(wrapper);
            if (rolesList.size() != roleIdList.size()) return Result.error("设置的角色有误");


            // 删除用户角色
            if (Objects.equals(type, UserDataSetTypeEnum.REMOVE.getValue())) {
                LambdaQueryWrapper<UserRoles> removeWrapper = new LambdaQueryWrapper<>();
                removeWrapper.eq(UserRoles::getUserId, userId);
                removeWrapper.in(UserRoles::getRoleId, roleIdList);

                this.remove(removeWrapper);
                return Result.success("删除用户角色成功");
            }

            List<UserRoles> userRolesList = new ArrayList<>();
            for (String roleId : roleIdList) {
                UserRoles userRoles = new UserRoles();
                userRoles.setUserId(userId);
                userRoles.setRoleId(roleId);
                userRolesList.add(userRoles);
            }

            //为用户重新设置角色，全部重新设置
            if (Objects.equals(type, UserDataSetTypeEnum.REFRESH.getValue())) {
                LambdaQueryWrapper<UserRoles> refreshWrapper = new LambdaQueryWrapper<>();
                refreshWrapper.eq(UserRoles::getUserId, userId);

                this.remove(refreshWrapper);
                this.saveBatch(userRolesList);
                return Result.success("新增用户角色成功");
            }

            //为用户在原有基础上新增角色
            if (Objects.equals(type, UserDataSetTypeEnum.ADD.getValue())) {
                LambdaQueryWrapper<UserRoles> addWrapper = new LambdaQueryWrapper<>();
                addWrapper.eq(UserRoles::getUserId, userId);
                addWrapper.in(UserRoles::getRoleId, roleIdList);
                if (this.count(addWrapper) > 0) return Result.error("用户角色已存在!");

                this.saveBatch(userRolesList);
                return Result.success("设置角色权限成功");
            }

            return Result.error("设置用户角色失败!");
        } catch (Exception e) {
            log.error("设置用户角色失败！ {}", e.getMessage());
            throw new ProgramException();
        }
    }

    @Override
    public Result<List<User>> getRoleUsersDetail(String roleId, String account, String nickname) {

        if (roleId.isEmpty()) return Result.error("请将参数补充完整");

        try {
            List<User> userListByRoleId = userRolesMapper.getUserListByRoleId(roleId, account, nickname);

            for (User user : userListByRoleId) {
                user.setPassword(null);
                user.setEmailFuzzyQuery(null);
                user.setPhoneFuzzyQuery(null);
//                user.setEmail(CustomEncryptorUtil.decrypt(user.getEmail()));
//                user.setPhoneNumber(CustomEncryptorUtil.decrypt(user.getPhoneNumber()));
                user.setEmail(null);
                user.setPhoneNumber(null);
            }

            return Result.success("获取角色用户列表成功！", userListByRoleId);
        } catch (Exception e) {
            log.error("获取角色用户列表失败！ {}", e.getMessage());
            throw new ProgramException();
        }
    }

    @Override
    @Transactional
    public Result<String> setRoleUsers(String roleId, String type, List<String> userIdList) {
        try {
            if (roleId.isEmpty() || type.isEmpty()) return Result.error("请将参数补充完整");
            if (UserDataSetTypeEnum.getEnumByValue(type) == null) return Result.error("type参数错误");
            if (userIdList == null || userIdList.isEmpty()) return Result.error("用户列表不能为空");

            // 校验角色信息
            LambdaQueryWrapper<Roles> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Roles::getId, roleId);
            queryWrapper.eq(Roles::getIsDelete, 0);

            Roles roles = rolesMapper.selectOne(queryWrapper);
            if (roles == null) return Result.error("角色不存在");

            // 校验用户信息
            LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(User::getId, userIdList);
            wrapper.eq(User::getIsDelete, 0);

            List<User> userList = userMapper.selectList(wrapper);
            if (userList.size() != userIdList.size()) return Result.error("设置的用户有误");


            // 删除角色用户
            if (Objects.equals(type, UserDataSetTypeEnum.REMOVE.getValue())) {
                LambdaQueryWrapper<UserRoles> removeWrapper = new LambdaQueryWrapper<>();
                removeWrapper.eq(UserRoles::getRoleId, roleId);
                removeWrapper.in(UserRoles::getUserId, userIdList);

                this.remove(removeWrapper);
                return Result.success("删除角色用户成功");
            }

            //为用户在原有基础上新增角色
            if (Objects.equals(type, UserDataSetTypeEnum.ADD.getValue())) {
                List<UserRoles> userRolesList = new ArrayList<>();
                for (String userId : userIdList) {
                    UserRoles userRoles = new UserRoles();
                    userRoles.setUserId(userId);
                    userRoles.setRoleId(roleId);
                    userRolesList.add(userRoles);
                }

                LambdaQueryWrapper<UserRoles> addWrapper = new LambdaQueryWrapper<>();
                addWrapper.eq(UserRoles::getRoleId, roleId);
                addWrapper.in(UserRoles::getUserId, userIdList);
                if (this.count(addWrapper) > 0) return Result.error("角色用户已存在!");

                this.saveBatch(userRolesList);
                return Result.success("新增角色用户成功");
            }

            //为用户重新设置角色，全部重新设置
            if (Objects.equals(type, UserDataSetTypeEnum.REFRESH.getValue())) {
                // 提取出旧角色用户
                List<User> userListByRoleId = userRolesMapper.getUserListByRoleId(roleId, null, null);

                // 将旧角色用户id放入map中
                Map<String, String> oldUserMap = new HashMap<>();
                for (User user : userListByRoleId) {
                    oldUserMap.put(user.getId(), user.getId());
                }

                // 将新角色用户id放入map中
                Map<String, String> newUserMap = new HashMap<>();
                for (String userId : userIdList) {
                    newUserMap.put(userId, userId);
                }

                // 需要删除的用户id
                List<String> removeList = new ArrayList<>();
                // 需要新增的用户id
                List<String> insertList = new ArrayList<>();

                // 获取需要删除的用户id，旧用户id去新用户map中校验，没有则需要删除
                for (String oldUserId : oldUserMap.keySet()) {
                    if (newUserMap.get(oldUserId) == null) removeList.add(oldUserId);
                }

                // 获取需要新增的用户id，新用户去旧用户map中校验，没有则需要新增
                for (String newUserId : newUserMap.keySet()) {
                    if (oldUserMap.get(newUserId) == null) insertList.add(newUserId);
                }

                // 删除角色用户
                LambdaQueryWrapper<UserRoles> deleteWrapper = new LambdaQueryWrapper<>();
                deleteWrapper.eq(UserRoles::getRoleId, roleId);
                deleteWrapper.in(UserRoles::getUserId, removeList);
                userRolesMapper.delete(deleteWrapper);

                // 重新设置角色用户
                for (String userId : insertList) {
                    UserRoles userRoles = new UserRoles();
                    userRoles.setUserId(userId);
                    userRoles.setRoleId(roleId);
                    userRolesMapper.insert(userRoles);
                }

                return Result.success("设置角色用户成功");
            }

            return Result.error("设置角色用户失败!");
        } catch (Exception e) {
            log.error("设置角色用户失败 {}", e.getMessage());
            throw new ProgramException();
        }
    }
}
